package com.anjufang.controller;

import com.anjufang.entity.GroupDetail;
import com.anjufang.entity.GroupInfo;
import com.anjufang.entity.SourceHouse;
import com.anjufang.mapper.GroupDetailMapper;
import com.anjufang.service.system.GroupDetailService;
import com.anjufang.service.system.GroupInfoService;
import com.anjufang.utils.Result;
import com.anjufang.utils.cache.RedisUtil;
import com.anjufang.utils.page.AppQuery;
import com.anjufang.utils.validator.Assert;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 抽签
 */
@RestController
@RequestMapping("draw")
public class DrawController extends BaseController {

    @Autowired
    private GroupInfoService groupInfoService;
    @Autowired
    private GroupDetailService groupDetailService;
    @Autowired
    private GroupDetailMapper groupDetailMapper;

    // 抽签缓存锁
    private static String LOCK_KEY = "anjufang.draw.lock";

    @PostMapping("start")
    public Result start(Long detailId, Integer type) {

        try {
            if (!tryLock()) {
                return Result.error("该房已被别人抢先一步，请重试");
            }
            Assert.isNull(detailId, "抽签编号不能为空");
            // 查询当前组用户
            GroupDetail groupDetail = new GroupDetail().selectOne("id = {0} and is_deleted = {1}", detailId, 0);
            if (null == groupDetail) {
                return Result.error("抽签失败！暂无该抽签人员信息");
            }
            if (groupDetail.getStatus().equals(1)) {
                return Result.error("抽签失败！请勿重复抽签");
            }
            // 查询小组信息
            GroupInfo groupInfo = new GroupInfo().selectById(groupDetail.getGroupId());
            Assert.isNull(groupInfo, "抽签失败！分组不存在");
            if (groupInfo.getStatus().equals(1)) {
                return Result.error("该组已完成抽签，请勿重复操作");
            }

            // 查询未分配房源
            List<SourceHouse> houseList = getHousesByType(type);
            if (CollectionUtils.isEmpty(houseList)) {
                return Result.error("抽签失败！房源不足");
            }
            // 打乱数据
            Collections.shuffle(houseList);
            // 分配房源
            drawHouse(groupDetail, houseList);
            return Result.ok().put("result", groupDetail)
                    .put("house", groupDetail.getAddress() + "#" + groupDetail.getFloor() + "#" + groupDetail.getRoomNo());

        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(e.getMessage());
        } finally {
            // 释放锁
            RedisUtil.deletenx(LOCK_KEY);
        }
    }

    private boolean tryLock() {
        return RedisUtil.setnx(LOCK_KEY, "1");
    }


    private List<SourceHouse> getHousesByType(Integer type) {
        List<SourceHouse> houseList;
        if (type == null) {
            // 普通用户从全部房源里抽
            houseList = new SourceHouse().selectList("status = {0} and is_deleted = {1}", 0, 0);
        } else {
            houseList = new SourceHouse().selectList("status = {0} and type = {1} and is_deleted = {2}", 0, type, 0);
        }
        return houseList;
    }

    /**
     * 未到场
     * @param detailId
     * @return
     */
    @GetMapping("late")
    public Result setLate(Long detailId) {
        Assert.isNull(detailId, "抽签编号不能为空");
        GroupDetail groupDetail = new GroupDetail().selectOne("id = {0} and is_deleted = 0", detailId);
        Assert.isNull(groupDetail, "设置失败！未找到该人员");
        if (!groupDetail.getStatus().equals(0)) {
            return Result.error("设置失败！该用户已完成抽签");
        }
        if (groupDetail.getArriveStatus().equals(1)) {
            return Result.error("请勿重复设置");
        }
        GroupDetail detail = new GroupDetail();
        detail.setId(detailId);
        detail.setArriveStatus(1);
        detail.setSortNum(getLastSort());
        detail.updateById();
        return Result.ok();
    }

    /**
     * 获取最后一个编号 + 1
     * @return
     */
    private int getLastSort() {
        GroupDetail detail = groupDetailMapper.getLast();
        if (null != detail) {
            return detail.getSortNum() + 1;
        }
        return 100000;
    }

    @Deprecated
    @PostMapping("start1")
    public Result start1(Long groupId, Long detailId) {

        Assert.isNull(groupId, "分组ID不能为空");
        Assert.isNull(detailId, "抽签编号不能为空");
        GroupInfo groupInfo = new GroupInfo().selectById(groupId);
        Assert.isNull(groupInfo, "抽签失败！分组不存在");

        if (groupInfo.getStatus().equals(1)) {
            return Result.error("该组已完成抽签，请勿重复操作");
        }
        // 查询当前组用户
        GroupDetail groupDetail = new GroupDetail().selectOne("id = {0} and group_id = {1} and is_deleted = {2}", detailId, groupId, 0);
        if (null == groupDetail) {
            return Result.error("抽签失败！暂无该抽签人员信息");
        }
        if (groupDetail.getStatus().equals(1)) {
            return Result.error("抽签失败！请勿重复抽签");
        }
        // 查询未分配房源
        List<SourceHouse> houseList = new SourceHouse().selectList("status = {0} and is_deleted = {1}", 0, 0);
        if (CollectionUtils.isEmpty(houseList)) {
            return Result.error("抽签失败！暂无房源数据");
        }

        // 房源分成：普通和特殊房源
        List<SourceHouse> normalHouseList = new ArrayList<>();
        List<SourceHouse> specialHouseList = new ArrayList<>();
        houseList.stream().forEach(item -> {
            if (item.getType().equals(0)) {
                normalHouseList.add(item);
            } else {
                specialHouseList.add(item);
            }
        });
        // 打乱数据
        Collections.shuffle(normalHouseList);
        Collections.shuffle(specialHouseList);

        // 先分配特殊房源，再分配普通房源，并更新房源为已分配
        // 特殊用户，分配特殊房源
        if (groupDetail.getType().equals(1)) {
            drawHouse(groupDetail, specialHouseList);
        }
        // 特殊用户未分配到特殊房源的，分配普通住房
        if (groupDetail.getType().equals(1)) {
            drawHouse(groupDetail, normalHouseList);
        }
        // 普通用户分配普通房源
        if (groupDetail.getType().equals(0)) {
            drawHouse(groupDetail, normalHouseList);
        }
        // 未分到的普通用户，分配特殊房源
        if (groupDetail.getType().equals(0)) {
            drawHouse(groupDetail, specialHouseList);
        }
        return Result.ok().put("result", groupDetail);
    }


    private boolean drawHouse(GroupDetail groupDetail, List<SourceHouse> houseList) {
        // 已分配用户，不处理
        if (!groupDetail.getStatus().equals(0)) {
            return false;
        }
        // 无房源数据，不分配
        if (CollectionUtils.isEmpty(houseList)) {
            return false;
        }
        for (SourceHouse house : houseList) {
            // 当前房源未分配
            if (house.getStatus().equals(0)) {
                // 更新抽签结果
                groupDetail.setHouseId(house.getId());
                groupDetail.setAddress(house.getAddress());
                groupDetail.setFloor(house.getFloor());
                groupDetail.setRoomNo(house.getRoomNo());
                groupDetail.setHouseType(house.getType());
                groupDetail.setHuxing(house.getHuxing());
                groupDetail.setAreaSpace(house.getAreaSpace());
                groupDetail.setRoomSpace(house.getRoomSpace());
                groupDetail.setUpdateTime(new Date());
                groupDetail.setStatus(1); // 抽签成功
                groupDetail.updateById();
                // 更新房源信息
                house.setUpdateTime(new Date());
                house.setStatus(1);
                house.updateById();
                return true;
            }
        }
        return false;
    }

    @GetMapping("result")
    public Result getResult(Long id) {
        Assert.isNull(id, "请选择您要查询的数据");
        GroupDetail groupDetail = new GroupDetail().selectById(id);
        if (null == groupDetail || !groupDetail.getIsDeleted().equals(0) || groupDetail.getStatus().equals(0)) {
            return Result.error("暂无抽签结果");
        }
        return Result.ok().put("result", groupDetail);
    }

    @GetMapping("groups")
    public Result listGroup(@RequestParam Map<String, Object> params) {

        AppQuery query = new AppQuery(params);
        List<GroupInfo> groupInfoList = groupInfoService.queryList(query);
        return Result.ok().put("groups", groupInfoList);
    }

    @GetMapping("details")
    public Result listDetail(@RequestParam Map<String, Object> params) {

        params.put("sidx", "sort_num");
        params.put("order", "asc");
        AppQuery query = new AppQuery(params);
        List<GroupDetail> groupDetailList = groupDetailService.queryList(query);
        return Result.ok().put("details", groupDetailList);
    }

    @GetMapping("houes")
    public Result listHouse(Integer type) {
        List<SourceHouse> houseList;
        if (null == type) {
            houseList = new SourceHouse().selectList("status = 0 and is_deleted = 0");
        } else {
            houseList = new SourceHouse().selectList("status = 0 and type = {0} and is_deleted = 0", type);
        }
        if (CollectionUtils.isEmpty(houseList)) {
            return Result.ok().put("houes", new ArrayList<>());
        }
        Collections.shuffle(houseList);
        List<String> list = houseList.stream().map(item -> item.getAddress() + "#" + item.getFloor() + "#" + item.getRoomNo()).collect(Collectors.toList());
        return Result.ok().put("houes", list);
    }

    @GetMapping("getUnArriveNum")
    public Result getUnArriveNum() {

        int unArriveNum = new GroupDetail().selectCount("arrive_status = 1 and is_deleted = 0");
        return Result.ok().put("unArriveNum", unArriveNum);
    }


}
